﻿using System.Diagnostics;
using System.Drawing.Text;
using System.Text;
using static System.Windows.Forms.VisualStyles.VisualStyleElement.Window;

namespace VersionControl
{
    
    public partial class Form1 : Form
    {
        string classPath = Application.StartupPath;
        string docsPath = "";
        string fileName = "";
        string latestCommit = "";
        
        public Form1()
        {
            
            InitializeComponent();
            /* for (int i = 0; i < 100; i++)
             {
                 ListViewItem item = new ListViewItem();
                 item.Text = i.ToString();
                 item.SubItems.Add(i.ToString());
                 item.SubItems.Add(i.ToString());
                 listView1.Items.Add(item);

             }*/
            docsPath = classPath + @"\docs";
            //确认文件夹是否已git初始化
            string gitPath = classPath + @"\.git";
            if (!Directory.Exists(gitPath))
            {//没有初始化git，进行git初始化
                GitRun("init");
            }
            //确认存储文件夹是否存在，不存在则创建
            if (!Directory.Exists(docsPath))
            {
                Directory.CreateDirectory(docsPath);

            }
            RefreshListView();
           

        }

        private void RefreshListView()
        {
            List<CommitItem> items = new List<CommitItem>();
            //尝试获取git log 的CommitItemlist
            if (!(GitRun("log") == "" || GitRun("log") == null))
            {
                items = RunGitLog();
            }
            //如果有，将commititem放进 ListView
            if (items.Count > 0)
            {
                listView1.Items.Clear();
                foreach (CommitItem item in items)
                {
                    if (item == items.First())
                    {
                        latestCommit= item.commitId;
                    }
                    ListViewItem i = new ListViewItem();
                    i.Text = item.fileName;
                    i.SubItems.Add(item.description);
                    i.SubItems.Add(item.changeDate);
                    i.SubItems.Add(item.commitId);
                    listView1.Items.Add(i);
                }
            }
        }

        private string EncodingTrans(string str)
        {
            //处理编码问题，git返回的中文是系统编码gb18030，转为应用的编码UTF-8
            Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
            Byte[] strTemp = Encoding.GetEncoding("gbk").GetBytes(str);
            str = Encoding.UTF8.GetString(strTemp);
            return str;
        }

        private List<CommitItem> RunGitLog()
        {
            string gitlog = GitRun("log");
            
            
            gitlog = EncodingTrans(gitlog);
            MessageBox.Show(gitlog);
            List<string> commitList = new List<string>();
            commitList = gitlog.Split("commit ").ToList();
            commitList.RemoveAt(0);
            string commitId = "";
            string txtName = "";
            string desc = "";
            string date = "";
            List<CommitItem> items = new List<CommitItem>();
            foreach (string commit in commitList)
            {
                //提交编号，取10位足够
                commitId = commit.Substring(0, 10);
                //获取date部分内容
                int indexOfDate = commit.IndexOf("Date: ");
                int indexOfDateEnd = commit.IndexOf(" +0800");
                date = commit.Substring(indexOfDate + 12, indexOfDateEnd - (indexOfDate + 12));
                //获取提交描述部分内容                
                int indexOfDescStart = commit.IndexOf("+0800") + 11;
                //int indexOfDescEnd = commit.LastIndexOf("'");
                desc = commit.Substring(indexOfDescStart);//, indexOfDescEnd-indexOfDescStart+1);
                desc = desc.Replace("'", "");
                //获取提交的更改文件名
                string gitShow = GitRun("show " + commitId);
                gitShow=EncodingTrans(gitShow);
                int indexFileNameStart = gitShow.LastIndexOf(@"b/docs/") + 7;
                int indexFileNameEnd = gitShow.LastIndexOf(".txt");
                gitShow = gitShow.Substring(indexFileNameStart, indexFileNameEnd - indexFileNameStart);
                txtName = gitShow;
                //封装，加入list
                CommitItem item = new CommitItem(commitId, txtName, desc, date);
                items.Add(item);
            }
            return items;
        }

        private void button1_Click(object sender, EventArgs e)
        {
            fileName = SelectPath();


        }



        private string SelectPath()
        {
            string path = Path.GetDirectoryName(this.Text);
            OpenFileDialog openFileDialog = new OpenFileDialog();
            if (openFileDialog.ShowDialog() == DialogResult.OK)
            {
                pathBox.Text = openFileDialog.FileName;
                path = openFileDialog.FileName;
            }
            return path;


        }

        private void pathBox_TextChanged(object sender, EventArgs e)
        {

        }

        private void Btn_GitCommit_Click(object sender, EventArgs e)
        {
            //将文件转换为TXT
            if (fileName == "")
            {
                MessageBox.Show("请先选择要提交的文件!", "错误");
                return;
            }
            if (textBox2.Text == null || textBox2.Text == "")
            {
                MessageBox.Show("请输入版本提交描述信息!", "错误");
                return;
            }
            //转换选种文件到本地docs文件夹下的txt
            FileToBase64Txt(fileName);
            GitRun("add .");
            var res=GitRun(@"commit -m "+"'"+textBox2.Text+"'");                       
            RefreshListView();
        }

        private void listView1_SelectedIndexChanged(object sender, EventArgs e)
        {

        }



        public string GitRun(string arguments)
        {
            //创建一个git的process
            var info = new ProcessStartInfo("git", arguments)
            {
                CreateNoWindow = true,
                RedirectStandardOutput = true,
                UseShellExecute = false,
                WorkingDirectory = classPath,
            };
            var process = new Process
            {
                StartInfo = info,
            };
            process.Start();
            return process.StandardOutput.ReadToEnd();
        }

        public void FileToBase64Txt(string file)
        {
            FileStream fs = new FileStream(file, FileMode.Open, FileAccess.Read);
            byte[] byteArray = new byte[fs.Length];
            fs.Read(byteArray, 0, byteArray.Length);
            fs.Close();
            string str = Convert.ToBase64String(byteArray);
            //处理文件名
            string[] strs = file.Split(@"\");//strs[strs.Count()-1] 即为所要转换的文件名
            string txtName = strs[strs.Count() - 1] + ".txt";
            File.WriteAllText(docsPath + @"\" + txtName, str);
        }

        public void Base64TxtToFile(string file)
        {

        }

        private void Btn_recover_Click(object sender, EventArgs e)
        {
            //检查是否有选中的文件
            if(listView1.CheckedItems==null|| listView1.CheckedItems.Count == 0)
            {
                MessageBox.Show("请先选中要恢复的文件", "错误");
                return;
            }
            if (listView1.CheckedItems.Count > 1)
            {
                MessageBox.Show("请一次选择一个文件", "错误");
                return;

            }
            //获取当前选中的文件
            ListViewItem listViewItem = listView1.CheckedItems[0];
            //打开保存文件对话框
            SaveFileDialog saveFileDialog = new SaveFileDialog();
            saveFileDialog.FileName = listViewItem.Text;
            saveFileDialog.RestoreDirectory = true;
            //第三个subitem是commitid
            string commitId = listViewItem.SubItems[3].Text;
            //根据commitid回滚版本
            GitRun("reset --hard " + commitId);
            //读取txt到str
            string base64str= File.ReadAllText(docsPath + @"\" + listViewItem.Text + ".txt");
            byte[] b= Convert.FromBase64String(base64str);
            Stream myStream;
            if (saveFileDialog.ShowDialog() == DialogResult.OK)
            {
                if ((myStream = saveFileDialog.OpenFile()) != null)
                { 
                    myStream.Write(b, 0, b.Length);
                    myStream.Close();
                }                
            }
            //GIT回到最新版本
            GitRun("reset --hard " + latestCommit);
            Refresh();

        }

        private void Btn_Clear_Click(object sender, EventArgs e)
        {
            string gitpath = classPath+ ".git";
            DialogResult res= MessageBox.Show("确定要清除所有文件版本吗？","确认",MessageBoxButtons.OKCancel);
            if (res == DialogResult.Cancel) return;
            if (Directory.Exists(gitpath))
            {
                DirectoryInfo di = new DirectoryInfo(gitpath);
                DeleteFileByDirectory(di);
            }
            if (Directory.Exists(docsPath))
            {
                DirectoryInfo di = new DirectoryInfo(docsPath);
                DeleteFileByDirectory(di);
            }
        }

        public void DeleteFileByDirectory(DirectoryInfo info)

        {

            foreach (DirectoryInfo newInfo in info.GetDirectories())

            {

                DeleteFileByDirectory(newInfo);

            }

            foreach (FileInfo newInfo in info.GetFiles())

            {

                newInfo.Attributes = newInfo.Attributes & ~(FileAttributes.Archive | FileAttributes.ReadOnly | FileAttributes.Hidden);

                newInfo.Delete();

            }

            info.Attributes = info.Attributes & ~(FileAttributes.Archive | FileAttributes.ReadOnly | FileAttributes.Hidden);

            info.Delete();



        }
    }

    public class CommitItem
    {
        public string fileName;
        public string description;
        public string changeDate;
        public string commitId;
        public CommitItem(string commitId, string fileName, string description, string changeDate)
        {
            this.commitId = commitId;
            this.fileName = fileName;
            this.description = description;
            this.changeDate = changeDate;
        }

    }
}